package com.cyberinsight.cps.cybersphere.modelparser.rapidminer.reader;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import com.cyberinsight.cps.cybersphere.modelparser.rapidminer.exception.ParseException;
import com.cyberinsight.cps.cybersphere.modelparser.rapidminer.parser.RapidminerModelParser;

/**
 * 压缩文件读取，通过压缩文件路径读取信息
 * 
 * @author guozihua
 *
 */
public class ZipFileReader implements IReader {
	public static final String UNZIP_TMP_DIR = "Q:/model/tmp/";
	public static final String WORK_DIR = "Q:/model/work/";

	@Override
	public Map<String, String> read(String arg) throws IOException, ParseException {
		Map<String, String> resultMap = new HashMap<String, String>();
		File zipFile = new File(arg);
		if (!zipFile.exists()) {
			throw new FileNotFoundException(arg + "压缩文件不存在");
		}
		// 1、读取zip文件中properties并进行判断解压后文件是否存在
		Properties props = this.getZipProperites(zipFile);
		if (hasWorkDir(props)) {
			resultMap.put("status", "exist");
			resultMap.put("info", "The zip file has been parsed.");
			return resultMap;
		}
		// 2、对上传的模型压缩文件进行解析
		String name = zipFile.getName().substring(zipFile.getName().lastIndexOf('\\') + 1,
				zipFile.getName().lastIndexOf('.'));
		String workPath = unZipFiles(zipFile, props);
		// 3、将解压后文件放入工作目录
		// String workPath = moveZipFile(unzipFileTmpPath, props);
		// 4、用Rapidminer对文件夹下文件解析Process
		// String
		// Process process = parse(workPath + File.separator + name +
		// RapidminerModelParser.CMP_SUFFIX);
		// process;
		String process = FileUtils.readFileToString(
				new File(workPath + File.separator + name + RapidminerModelParser.CMP_SUFFIX),
				Charset.defaultCharset());
		resultMap.put("status", "success");
		resultMap.put("info", process);
		resultMap.put("namespace", props.getProperty("namespace", ""));
		resultMap.put("author", props.getProperty("author", ""));
		resultMap.put("company", props.getProperty("company", ""));
		resultMap.put("title", props.getProperty("title", ""));
		return resultMap;
	}

	/**
	 * 获取压缩文件中配置信息
	 * 
	 * @param zipFile
	 * @return
	 * @throws IOException
	 */
	@SuppressWarnings("resource")
	private Properties getZipProperites(File zipFile) throws IOException {
		Properties props = new Properties();
		ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"));
		String name = zipFile.getName().substring(zipFile.getName().lastIndexOf('\\') + 1,
				zipFile.getName().lastIndexOf('.'));
		ZipEntry propEntry = zip.getEntry(name + RapidminerModelParser.PROP_SUFFIX);
		try (InputStream in = zip.getInputStream(propEntry)) {
			props.load(in);
		}
		return props;
	}

	/**
	 * 判断是否存在工作目录
	 * 
	 * @param props
	 * @return
	 * @throws ParseException
	 */
	private boolean hasWorkDir(Properties props) throws ParseException {
		String nameSpace = props.getProperty("namespace");
		String name = props.getProperty("name");
		String version = props.getProperty("version");
		String destPath = WORK_DIR + File.separator + nameSpace + File.separator + name + File.separator + version;

		if (!(StringUtils.isNotBlank(nameSpace) && StringUtils.isNotBlank(name) && StringUtils.isNotBlank(version))) {
			throw new ParseException("namespace、name、version不能为空");
		}
		File destFile = new File(destPath);
		if (destFile.exists()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 解压文件
	 * 
	 * @param zipFile
	 * @return
	 * @throws IOException
	 */
	@SuppressWarnings("resource")
	private String unZipFiles(File zipFile, Properties props) throws IOException {
		String nameSpace = props.getProperty("namespace");
		String name = props.getProperty("name");
		String version = props.getProperty("version");
		String destPath = WORK_DIR + File.separator + nameSpace + File.separator + name + File.separator + version
				+ File.separator;
		ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"));// 解决中文文件夹乱码
		File pathFile = new File(destPath);
		if (!pathFile.exists()) {
			pathFile.mkdirs();
		}
		for (Enumeration<? extends ZipEntry> entries = zip.entries(); entries.hasMoreElements();) {
			InputStream in = null;
			FileOutputStream out = null;
			try {
				ZipEntry entry = (ZipEntry) entries.nextElement();
				String zipEntryName = entry.getName();
				in = zip.getInputStream(entry);
				String outPath = (destPath + zipEntryName).replaceAll("\\*", "/");

				// 判断路径是否存在,不存在则创建文件路径
				File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
				if (!file.exists()) {
					file.mkdirs();
				}
				// 判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
				if (new File(outPath).isDirectory()) {
					continue;
				}
				// 输出文件路径信息
				out = new FileOutputStream(outPath);
				byte[] buf1 = new byte[1024];
				int len;
				while ((len = in.read(buf1)) > 0) {
					out.write(buf1, 0, len);
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			} finally {
				if (in != null) {
					in.close();
				}
				if (out != null) {
					out.close();
				}
			}
		}
		return destPath;
	}

}
